package cn.tx.redis7.controller;

import cn.hutool.core.util.IdUtil;
import com.google.common.primitives.Ints;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @author jizenan
 * @date 2025/6/18
 * Description:
 */
@RestController
public class RedPackageController {

    public static final String RED_PACKAGE_KEY = "redpackage:";
    public static final String RED_PACKAGE_CONSUME_KEY = "redpackage:consume:";

    @Autowired
    private RedisTemplate redisTemplate;

    @RequestMapping("/send")
    public String sendRedPackage(int totalMoney,int redPackageNum){
        //1 拆红包，将总金额totalMoney拆分成redPackageNum个子红包
        //通过拆分红包算法后获得多个子红包数组
        Integer[] splitRedPackages = splitRedPackageAlgorithm(totalMoney,redPackageNum);

        //2 发红包并保存到list结构里面且设置过期时间
        String key = RED_PACKAGE_KEY + IdUtil.simpleUUID();
        redisTemplate.opsForList().leftPushAll(key,splitRedPackages);
        redisTemplate.expire(key,1, TimeUnit.DAYS);
        //3 发红包OK，返回前台显示
        return key + "\t" + Ints.asList(Arrays.stream(splitRedPackages).mapToInt(Integer::valueOf).toArray());
    }

    @RequestMapping("/rob")
    public String robRedPackage(String redPackageKey,int userId){
        //1 验证某个用户是否抢过红包，不可以重复抢
        return null;
    }

    /**
     * 3 拆红包算法--->二倍均值算法
     * */
    private Integer[] splitRedPackageAlgorithm(int totalMoney,int redPackageNum){
        Integer[] redPackageNums = new Integer[redPackageNum];
        //已经被抢抢夺的红包金额
        int useMoney = 0;
        for (int i = 0; i < redPackageNum; i++) {
            //如果只发5个，这就是第5个红包
            if(i == redPackageNum - 1){
                redPackageNums[i] = totalMoney - useMoney;
            }else{
                //二倍均值算法，每次拆分后塞进子红包的金额 = 随机区间(0,(剩余红包金额M ÷ 剩余红包个数N) * 2)
                int avgMoney = ((totalMoney - useMoney) / (redPackageNum - 1)) * 2;
                redPackageNums[i] = 1 + new Random().nextInt(avgMoney - 1);
            }
            useMoney = useMoney + redPackageNums[i];
        }
        return redPackageNums;
    }

    public static void main(String[] args) {
        //sendRedPackage(100,5);
        int totalAmount = 10000; // 100元 = 10000分
        int totalPeople = 5;

        int[] amounts = divideRedPacket(totalAmount, totalPeople);

        System.out.println("红包分配结果：");
        for (int i = 0; i < amounts.length; i++) {
            System.out.printf("第%d个人：%.2f元\n", i + 1, amounts[i] / 100.0);
        }

        int sum = Arrays.stream(amounts).sum();
        System.out.printf("总金额验证：%.2f元\n", sum / 100.0);
    }

    /**
     * 打乱数组顺序
     * @param array 要打乱的数组
     */
    private static void shuffleArray(int[] array) {
        Random random = new Random();
        for (int i = array.length - 1; i > 0; i--) {
            int index = random.nextInt(i + 1);
            int temp = array[index];
            array[index] = array[i];
            array[i] = temp;
        }
    }

    /**
     * 拆分红包
     * @param totalAmount 总金额（单位：分）
     * @param totalPeople 总人数
     * @return 每个人分到的金额数组（单位：分）
     */
    public static int[] divideRedPacket(int totalAmount, int totalPeople) {
        if (totalAmount <= 0 || totalPeople <= 0) {
            throw new IllegalArgumentException("总金额和总人数必须大于0");
        }
        if (totalAmount < totalPeople) {
            throw new IllegalArgumentException("总金额不能小于总人数");
        }

        int[] amounts = new int[totalPeople];
        int remainingAmount = totalAmount;
        int remainingPeople = totalPeople;

        Random random = new Random();

        // 给前n-1个人随机分配金额
        for (int i = 0; i < totalPeople - 1; i++) {
            // 保证每个人至少分到1分钱，且剩余金额足够分给剩下的人
            int max = remainingAmount - remainingPeople + 1;
            int amount = random.nextInt(max) + 1;

            amounts[i] = amount;
            remainingAmount -= amount;
            remainingPeople--;
        }

        // 最后一个人分得剩余所有金额
        amounts[totalPeople - 1] = remainingAmount;

        // 为了更公平，可以打乱顺序
        shuffleArray(amounts);

        return amounts;
    }
}
